#include "gtest/gtest.h"
#include "viml/compiler.h"
#include "viml/vm.h"
#include "viml/scope_manager.h"

using namespace viml;

class ScopeBasicTest : public ::testing::Test {
protected:
    Compiler compiler;
    VM vm;
    
    Value execute_source(const std::string& source) {
        auto bytecode = compiler.compile(source, "<test>");
        return vm.execute(bytecode);
    }
};

// 测试全局作用域
TEST_F(ScopeBasicTest, GlobalScope) {
    std::string source = R"(
        let g:x = 42
        echo g:x
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("x"));
    EXPECT_EQ(vm.get_global("x").as_number(), 42);
}

// 测试隐式全局作用域
TEST_F(ScopeBasicTest, ImplicitGlobalScope) {
    std::string source = R"(
        let x = 100
        echo x
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("x"));
    EXPECT_EQ(vm.get_global("x").as_number(), 100);
}

// 测试Vim内置变量
TEST_F(ScopeBasicTest, VimBuiltinVariables) {
    std::string source = R"(
        echo v:true
        echo v:false
        echo v:null
    )";
    
    EXPECT_NO_THROW(execute_source(source));
}

// 测试环境变量访问
TEST_F(ScopeBasicTest, EnvironmentVariable) {
    // 设置一个测试环境变量
    setenv("VIML_TEST_VAR", "test_value", 1);
    
    std::string source = R"(
        let g:x = $VIML_TEST_VAR
        echo g:x
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("x"));
    EXPECT_EQ(vm.get_global("x").as_string(), "test_value");
    
    // 清理
    unsetenv("VIML_TEST_VAR");
}

// 测试作用域隔离（准备为函数作用域）
TEST_F(ScopeBasicTest, ScopeIsolationPrep) {
    std::string source = R"(
        let g:global_var = 1
        let x = 2
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("global_var"));
    EXPECT_TRUE(vm.has_global("x"));
}

// 测试ScopeManager直接使用
TEST(ScopeManagerTest, BasicOperations) {
    ScopeManager sm;
    
    // 测试全局作用域
    sm.store(ScopeId::GLOBAL, "x", Value::make_number(42));
    Value v = sm.load(ScopeId::GLOBAL, "x");
    EXPECT_TRUE(v.is_number());
    EXPECT_EQ(v.as_number(), 42);
}

// 测试作用域前缀解析
TEST(ScopeManagerTest, ScopePrefixParsing) {
    EXPECT_EQ(parse_scope_prefix('g'), ScopeId::GLOBAL);
    EXPECT_EQ(parse_scope_prefix('l'), ScopeId::LOCAL);
    EXPECT_EQ(parse_scope_prefix('s'), ScopeId::SCRIPT);
    EXPECT_EQ(parse_scope_prefix('a'), ScopeId::ARG);
    EXPECT_EQ(parse_scope_prefix('v'), ScopeId::VIM);
    EXPECT_EQ(parse_scope_prefix('$'), ScopeId::ENV);
    
    EXPECT_THROW(parse_scope_prefix('x'), ScopeException);
}

// 测试变量名解析
TEST(ScopeManagerTest, VariableNameParsing) {
    auto [scope1, name1] = parse_variable_name("g:test");
    EXPECT_EQ(scope1, ScopeId::GLOBAL);
    EXPECT_EQ(name1, "test");
    
    auto [scope2, name2] = parse_variable_name("l:local_var");
    EXPECT_EQ(scope2, ScopeId::LOCAL);
    EXPECT_EQ(name2, "local_var");
    
    auto [scope3, name3] = parse_variable_name("plain_var");
    EXPECT_EQ(scope3, ScopeId::GLOBAL);
    EXPECT_EQ(name3, "plain_var");
}
